#ifndef MAVLINKHANDLER_H
#define MAVLINKHANDLER_H

#include <QObject>
#include <QQueue>
#include "MavlinkHandler/connection/connection_udp.h"
#include "MavlinkHandler/connection/connection_tcp.h"
#include "MavlinkHandler/connection/connection_serial.h"
#include "MavlinkHandler/connection/mavlink_message_handler.h"

/// MavlinkHandler
class MavlinkHandler
{

public:
    using Callback = std::function<void(const mavlink_message_t&)>;

    MavlinkHandler();
    virtual ~MavlinkHandler();

    // Massage prase
    void receive_message(mavlink_message_t& message, Connection* connection);
    bool send_message(mavlink_message_t& message);

    // Message register
    void register_one(uint16_t msg_id, Callback callback, const void* cookie){mMavMsgHandler.register_one(msg_id,callback,cookie);};
    void register_all(Callback callback, const void* cookie)                 {mMavMsgHandler.register_all(callback,cookie);};
    void unregister_one(uint16_t msg_id, const void* cookie)                 {mMavMsgHandler.unregister_one(msg_id,cookie);};
    void unregister_all(const void* cookie)                                  {mMavMsgHandler.unregister_all(cookie);};

    // Connection
    ConnectionResult add_udp_connection(const std::string& local_ip, int local_port);
    ConnectionResult add_tcp_connection( const std::string& remote_ip, int remote_port);
    ConnectionResult add_serial_connection( const std::string& dev_path, int baudrate,bool flow_control);
    ConnectionResult setup_udp_remote(const std::string& remote_ip, int remote_port);

private:

    void add_connection(std::shared_ptr<Connection> new_connection);
    static uint8_t get_target_system_id(const mavlink_message_t& message);
    static uint8_t get_target_component_id(const mavlink_message_t& message);

    MAVLinkMessageHandler mMavMsgHandler;
    bool _message_logging_on{false};
    std::atomic<bool> _should_exit = {false};
    std::mutex _connections_mutex{};
    std::vector<std::shared_ptr<Connection>> _connections{};
};

#endif // MAVLINKHANDLER_H
